<template>
  <div ref="item"
       class="vue-grid-item"
       :class="classObj"
       :style="style"
       :id="id"
  >
    <slot></slot>
    <span v-if="resizableAndNotStatic" ref="handle" :class="resizableHandleClass"></span>
  </div>
</template>

<script>

import interact from 'interactjs'
import { setTopLeft, setTopRight, setTransformRtl, setTransform } from './helpers/utils'
import { getControlPosition, createCoreData } from './helpers/draggableUtils'
import { getColsFromBreakpoint } from './helpers/responsiveUtils'
import { getDocumentDir } from './helpers/DOM'

export default {
  name: 'GridItem',
  props: {
    isDraggable: {
      type: Boolean,
      required: false,
      default: null
    },
    isResizable: {
      type: Boolean,
      required: false,
      default: null
    },
    static: {
      type: Boolean,
      required: false,
      default: false
    },
    minH: {
      type: Number,
      required: false,
      default: 1
    },
    minW: {
      type: Number,
      required: false,
      default: 1
    },
    maxH: {
      type: Number,
      required: false,
      default: Infinity
    },
    maxW: {
      type: Number,
      required: false,
      default: Infinity
    },
    x: {
      type: Number,
      required: true
    },
    y: {
      type: Number,
      required: true
    },
    w: {
      type: Number,
      required: true
    },
    h: {
      type: Number,
      required: true
    },
    id: {
      required: true
    },
    dragIgnoreFrom: {
      type: String,
      required: false,
      default: 'a, button'
    },
    dragAllowFrom: {
      type: String,
      required: false,
      default: null
    },
    resizeIgnoreFrom: {
      type: String,
      required: false,
      default: 'a, button'
    },
    preserveAspectRatio: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  inject: ['eventBus', 'gridLayout'],
  data () {
    return {
      cols: 1,
      containerWidth: 100,
      rowHeight: 30,
      margin: [10, 10],
      maxRows: Infinity,
      draggable: null,
      resizable: null,
      useCssTransforms: true,
      useStyleCursor: true,

      isDragging: false,
      dragging: null,
      isResizing: false,
      resizing: null,
      isCovering: false,
      lastX: NaN,
      lastY: NaN,
      lastW: NaN,
      lastH: NaN,
      style: {},
      rtl: false,

      dragEventSet: false,
      resizeEventSet: false,

      previousW: null,
      previousH: null,
      previousX: null,
      previousY: null,
      innerX: this.x,
      innerY: this.y,
      innerW: this.w,
      innerH: this.h
    }
  },
  computed: {
    classObj () {
      return {
        'vue-resizable': this.resizableAndNotStatic,
        static: this.static,
        resizing: this.isResizing,
        'vue-draggable-dragging': this.isDragging,
        cssTransforms: this.useCssTransforms,
        'render-rtl': this.renderRtl,
        'disable-userselect': this.isDragging,
        'no-touch': this.isAndroid && this.draggableOrResizableAndNotStatic,
        covering: this.isCovering
      }
    },
    resizableAndNotStatic () {
      return this.resizable && !this.static
    },
    draggableOrResizableAndNotStatic () {
      return (this.draggable || this.resizable) && !this.static
    },
    isAndroid () {
      return false
    },
    renderRtl () {
      return (this.gridLayout.isMirrored) ? !this.rtl : this.rtl
    },
    resizableHandleClass () {
      if (this.renderRtl) {
        return 'vue-resizable-handle vue-rtl-resizable-handle'
      } else {
        return 'vue-resizable-handle'
      }
    }
  },
  watch: {
    static () {
      this.tryMakeDraggable()
      this.tryMakeResizable()
    },
    isDraggable () {
      this.draggable = this.isDraggable
    },
    draggable () {
      this.tryMakeDraggable()
    },
    isResizable () {
      this.resizable = this.isResizable
    },
    resizable () {
      this.tryMakeResizable()
    },
    rowHeight () {
      this.updateStyle()
      this.emitContainerResized()
    },
    cols () {
      this.tryMakeResizable()
      this.updateStyle()
      this.emitContainerResized()
    },
    containerWidth () {
      this.tryMakeResizable()
      this.updateStyle()
      this.emitContainerResized()
    },
    x (value) {
      this.innerX = value
      this.updateStyle()
    },
    y (value) {
      this.innerY = value
      this.updateStyle()
    },
    h (value) {
      this.innerH = value
      this.updateStyle()
    },
    w (value) {
      this.innerW = value
      this.updateStyle()
    },
    renderRtl () {
      this.tryMakeResizable()
      this.updateStyle()
    },
    minH () {
      this.tryMakeResizable()
    },
    maxH () {
      this.tryMakeResizable()
    },
    minW () {
      this.tryMakeResizable()
    },
    maxW () {
      this.tryMakeResizable()
    },
    '$parent.margin' (margin) {
      if (!margin || (margin[0] === this.margin[0] && margin[1] === this.margin[1])) return
      this.margin = margin.map(m => Number(m))
      this.updateStyle()
      this.emitContainerResized()
    }
  },
  created () {
    // Accessible references of functions for removing in beforeUnmount
    this.updateWidthHandler = width => {
      this.updateWidth(width)
    }
    this.updateStyleHandler = layout => {
      this.updateStyle(layout)
    }
    this.setDraggableHandler = isDraggable => {
      if (this.isDraggable === null) {
        this.draggable = isDraggable
      }
    }
    this.setResizableHandler = isResizable => {
      if (this.isResizable === null) {
        this.resizable = isResizable
      }
    }
    this.setRowHeightHandler = rowHeight => {
      this.rowHeight = rowHeight
    }
    this.setMaxRowsHandler = maxRows => {
      this.maxRows = maxRows
    }
    this.directionChangeHandler = () => {
      this.rtl = getDocumentDir() === 'rtl'
      this.updateStyle()
    }
    this.setColNum = (colNum) => {
      this.cols = parseInt(colNum)
    }

    this.eventBus.on('updateWidth', this.updateWidthHandler)
    this.eventBus.on('updateGridItemStyle', this.updateStyleHandler)
    this.eventBus.on('setDraggable', this.setDraggableHandler)
    this.eventBus.on('setResizable', this.setResizableHandler)
    this.eventBus.on('setRowHeight', this.setRowHeightHandler)
    this.eventBus.on('setMaxRows', this.setMaxRowsHandler)
    this.eventBus.on('directionChange', this.directionChangeHandler)
    this.eventBus.on('setColNum', this.setColNum)

    this.rtl = getDocumentDir() === 'rtl'
  },
  beforeUnmount () {
    console.log('beforeUnmount', this.id)
    // Remove listeners
    this.eventBus.off('updateWidth', this.updateWidthHandler)
    this.eventBus.off('updateGridItemStyle', this.updateStyleHandler)
    this.eventBus.off('setDraggable', this.setDraggableHandler)
    this.eventBus.off('setResizable', this.setResizableHandler)
    this.eventBus.off('setRowHeight', this.setRowHeightHandler)
    this.eventBus.off('setMaxRows', this.setMaxRowsHandler)
    this.eventBus.off('directionChange', this.directionChangeHandler)
    this.eventBus.off('setColNum', this.setColNum)
  },
  unmounted () {
    if (this.interactInstance) {
      this.interactInstance.unset()
    }
  },
  mounted () {
    if (this.gridLayout.responsive && this.gridLayout.lastBreakpoint) {
      this.cols = getColsFromBreakpoint(this.gridLayout.lastBreakpoint, this.gridLayout.cols)
    } else {
      this.cols = this.gridLayout.colNum
    }
    this.rowHeight = this.gridLayout.rowHeight
    this.containerWidth = this.gridLayout.width !== null ? this.gridLayout.width : 100
    this.margin = this.gridLayout.margin !== undefined ? this.gridLayout.margin : [10, 10]
    this.maxRows = this.gridLayout.maxRows

    if (this.isDraggable === null) {
      this.draggable = this.gridLayout.isDraggable
    } else {
      this.draggable = this.isDraggable
    }
    if (this.isResizable === null) {
      this.resizable = this.gridLayout.isResizable
    } else {
      this.resizable = this.isResizable
    }
    this.useCssTransforms = this.gridLayout.useCssTransforms
    this.useStyleCursor = this.gridLayout.useStyleCursor
    this.updateStyle()
  },
  methods: {
    updateStyle () {
      if (this.x + this.w > this.cols) {
        this.innerX = 0
        this.innerW = (this.w > this.cols) ? this.cols : this.w
      } else {
        this.innerX = this.x
        this.innerW = this.w
      }
      const pos = this.calcPosition(this.innerX, this.innerY, this.innerW, this.innerH)
      if (this.isDragging) {
        pos.top = this.dragging.top
        // Add rtl support
        if (this.renderRtl) {
          pos.right = this.dragging.left
        } else {
          pos.left = this.dragging.left
        }
      }
      if (this.isResizing) {
        pos.width = this.resizing.width
        pos.height = this.resizing.height
      }

      let style
      // CSS Transforms support (default)
      if (this.useCssTransforms) {
        // Add rtl support
        if (this.renderRtl) {
          style = setTransformRtl(pos.top, pos.right, pos.width, pos.height)
        } else {
          style = setTransform(pos.top, pos.left, pos.width, pos.height)
        }
      } else {
        // top,left (slow)
        // Add rtl support
        if (this.renderRtl) {
          style = setTopRight(pos.top, pos.right, pos.width, pos.height)
        } else {
          style = setTopLeft(pos.top, pos.left, pos.width, pos.height)
        }
      }
      this.style = style
      // [X] Special style for some widget
      // destructive inner code -> need become a feature
      this.isCovering = !!(this.gridLayout.coverLayoutItem &&
          this.gridLayout.coverLayoutItem.id === this.id &&
          ~this.id.indexOf('APP_WIDGET_'))
    },
    emitContainerResized () {
      // this.style has width and height with trailing 'px'. The
      // resized event is without them
      const styleProps = {}
      for (const prop of ['width', 'height']) {
        const val = this.style[prop]
        const matches = val.match(/^(\d+)px$/)
        if (!matches) {
          return
        }
        styleProps[prop] = matches[1]
      }
      this.$emit('container-resized', this.id, this.h, this.w, styleProps.height, styleProps.width)
    },
    handleResize (event) {
      if (this.static) return
      const position = getControlPosition(event)
      // Get the current drag point from the event. This is used as the offset.
      if (position == null) return // not possible but satisfies flow
      const {
        x,
        y
      } = position

      const newSize = {
        width: 0,
        height: 0
      }
      let pos
      switch (event.type) {
        case 'resizestart': {
          this.previousW = this.innerW
          this.previousH = this.innerH
          pos = this.calcPosition(this.innerX, this.innerY, this.innerW, this.innerH)
          newSize.width = pos.width
          newSize.height = pos.height
          this.resizing = newSize
          this.isResizing = true
          break
        }
        case 'resizemove': {
          // console.log('### resize => ' + event.type + ', lastW=' + this.lastW + ', lastH=' + this.lastH);
          const coreEvent = createCoreData(this.lastW, this.lastH, x, y)
          if (this.renderRtl) {
            newSize.width = this.resizing.width - coreEvent.deltaX
          } else {
            newSize.width = this.resizing.width + coreEvent.deltaX
          }
          newSize.height = this.resizing.height + coreEvent.deltaY
          // console.log('### resize => ' + event.type + ', deltaX=' + coreEvent.deltaX + ', deltaY=' + coreEvent.deltaY);
          this.resizing = newSize
          break
        }
        case 'resizeend': {
          // console.log('### resize end => x=' +this.innerX + ' y=' + this.innerY + ' w=' + this.innerW + ' h=' + this.innerH);
          pos = this.calcPosition(this.innerX, this.innerY, this.innerW, this.innerH)
          newSize.width = pos.width
          newSize.height = pos.height
          // console.log('### resize end => ' + JSON.stringify(newSize));
          this.resizing = null
          this.isResizing = false
          break
        }
      }
      // Get new WH
      pos = this.calcWH(newSize.height, newSize.width)
      if (pos.w < this.minW) {
        pos.w = this.minW
      }
      if (pos.w > this.maxW) {
        pos.w = this.maxW
      }
      if (pos.h < this.minH) {
        pos.h = this.minH
      }
      if (pos.h > this.maxH) {
        pos.h = this.maxH
      }
      if (pos.h < 1) {
        pos.h = 1
      }
      if (pos.w < 1) {
        pos.w = 1
      }

      this.lastW = x
      this.lastH = y

      if (this.innerW !== pos.w || this.innerH !== pos.h) {
        this.$emit('resize', this.id, pos.h, pos.w, newSize.height, newSize.width)
      }
      if (event.type === 'resizeend' &&
          (this.previousW !== this.innerW || this.previousH !== this.innerH)) {
        this.$emit('resized', this.id, pos.h, pos.w, newSize.height, newSize.width)
      }
      this.eventBus.emit('resizeEvent', event.type, this.id, this.innerX, this.innerY, pos.h, pos.w)
    },
    handleDrag (event) {
      if (this.static) return
      if (this.isResizing) return
      const position = getControlPosition(event)

      // Get the current drag point from the event. This is used as the offset.
      if (position === null) return // not possible but satisfies flow
      const {
        x,
        y
      } = position

      const newPosition = {
        top: 0,
        left: 0
      }

      switch (event.type) {
        case 'dragstart': {
          this.previousX = this.innerX
          this.previousY = this.innerY
          const parentRect = event.target.offsetParent.getBoundingClientRect()
          const clientRect = event.target.getBoundingClientRect()
          if (this.renderRtl) {
            newPosition.left = (clientRect.right - parentRect.right) * -1
          } else {
            newPosition.left = clientRect.left - parentRect.left
          }
          newPosition.top = clientRect.top - parentRect.top
          this.dragging = newPosition
          this.isDragging = true
          break
        }
        case 'dragend': {
          if (!this.isDragging) return
          const parentRect = event.target.offsetParent.getBoundingClientRect()
          const clientRect = event.target.getBoundingClientRect()
          // Add rtl support
          if (this.renderRtl) {
            newPosition.left = (clientRect.right - parentRect.right) * -1
          } else {
            newPosition.left = clientRect.left - parentRect.left
          }
          newPosition.top = clientRect.top - parentRect.top
          // console.log('### drag end => ' + JSON.stringify(newPosition));
          // console.log('### DROP: ' + JSON.stringify(newPosition));
          this.dragging = null
          this.isDragging = false

          // [X] drag end don't trigger click
          const target = event.target
          const preventClickProcess = (event) => {
            event.stopImmediatePropagation()
            // after prevent click immediately remove listener avoid other effects
            interact(target).off('click', preventClickProcess, true)
          }
          interact(target).on('click', preventClickProcess, true /* useCapture */)

          break
        }
        case 'dragmove': {
          const coreEvent = createCoreData(this.lastX, this.lastY, x, y)
          // Add rtl support
          if (this.renderRtl) {
            newPosition.left = this.dragging.left - coreEvent.deltaX
          } else {
            newPosition.left = this.dragging.left + coreEvent.deltaX
          }
          newPosition.top = this.dragging.top + coreEvent.deltaY
          // console.log('### drag => ' + event.type + ', x=' + x + ', y=' + y);
          // console.log('### drag => ' + event.type + ', deltaX=' + coreEvent.deltaX + ', deltaY=' + coreEvent.deltaY);
          // console.log('### drag end => ' + JSON.stringify(newPosition));
          this.dragging = newPosition
          break
        }
      }

      // console.log('newPosition', JSON.stringify(newPosition));

      // Get new XY
      let pos
      if (this.renderRtl) {
        pos = this.calcXY(newPosition.top, newPosition.left)
      } else {
        pos = this.calcXY(newPosition.top, newPosition.left)
      }

      this.lastX = x
      this.lastY = y

      // console.log(`### pos: `, JSON.stringify(pos));
      // console.log(`### lastX: ${this.lastX} lastY: ${this.lastY}`);

      if (this.innerX !== pos.x || this.innerY !== pos.y) {
        this.$emit('move', this.id, pos.x, pos.y)
      }
      if (event.type === 'dragend' && (this.previousX !== this.innerX || this.previousY !== this.innerY)) {
        this.$emit('moved', this.id, pos.x, pos.y)
      }
      this.eventBus.emit('dragEvent', {
        type: event.type,
        updatingLayout: {
          id: this.id,
          x: pos.x,
          y: pos.y,
          h: this.innerH,
          w: this.innerW
        },
        newPosition,
        gridSize: {
          cellWidth: this.calcColWidth(),
          cellHeight: this.rowHeight
        }
      })
    },
    calcPosition (x, y, w, h) {
      const colWidth = this.calcColWidth()
      // add rtl support
      let position
      if (this.renderRtl) {
        position = {
          right: Math.round(colWidth * x + (x + 1) * this.margin[0]),
          top: Math.round(this.rowHeight * y + (y + 1) * this.margin[1]),
          // 0 * Infinity === NaN, which causes problems with resize constraint;
          // Fix this if it occurs.
          // Note we do it here rather than later because Math.round(Infinity) causes deopt
          width: w === Infinity ? w : Math.round(colWidth * w + Math.max(0, w - 1) * this.margin[0]),
          height: h === Infinity ? h : Math.round(this.rowHeight * h + Math.max(0, h - 1) * this.margin[1])
        }
      } else {
        position = {
          left: Math.round(colWidth * x + (x + 1) * this.margin[0]),
          top: Math.round(this.rowHeight * y + (y + 1) * this.margin[1]),
          // 0 * Infinity === NaN, which causes problems with resize constriants;
          // Fix this if it occurs.
          // Note we do it here rather than later because Math.round(Infinity) causes deopt
          width: w === Infinity ? w : Math.round(colWidth * w + Math.max(0, w - 1) * this.margin[0]),
          height: h === Infinity ? h : Math.round(this.rowHeight * h + Math.max(0, h - 1) * this.margin[1])
        }
      }
      // console.log(JSON.stringify(position));
      return position
    },
    /**
     * Translate x and y coordinates from pixels to grid units.
     * @param  {Number} top  Top position (relative to parent) in pixels.
     * @param  {Number} left Left position (relative to parent) in pixels.
     * @return {Object} x and y in grid units.
     */
    // TODO check if this function needs change in order to support rtl.
    calcXY (top, left) {
      const colWidth = this.calcColWidth()

      // left = colWidth * x + margin * (x + 1)
      // l = cx + m(x+1)
      // l = cx + mx + m
      // l - m = cx + mx
      // l - m = x(c + m)
      // (l - m) / (c + m) = x
      // x = (left - margin) / (coldWidth + margin)

      let x = Math.round((left - this.margin[0]) / (colWidth + this.margin[0]))
      let y = Math.round((top - this.margin[1]) / (this.rowHeight + this.margin[1]))

      // Capping
      x = Math.max(Math.min(x, this.cols - this.innerW), 0)
      y = Math.max(Math.min(y, this.maxRows - this.innerH), 0)

      return {
        x,
        y
      }
    },
    // Helper for generating column width
    calcColWidth () {
      const colWidth = (this.containerWidth - (this.margin[0] * (this.cols + 1))) / this.cols
      !this && console.log('### COLS=' + this.cols + ' COL WIDTH=' + colWidth + ' MARGIN ' + this.margin[0])
      return colWidth
    },
    /**
     * Given a height and width in pixel values, calculate grid units.
     * @param  {Number} height Height in pixels.
     * @param  {Number} width  Width in pixels.
     * @param  {Boolean} autoSizeFlag  function autoSize identifier.
     * @return {Object} w, h as grid units.
     */
    calcWH (height, width, autoSizeFlag = false) {
      const colWidth = this.calcColWidth()
      // width = colWidth * w - (margin * (w - 1))
      // ...
      // w = (width + margin) / (colWidth + margin)
      let w = Math.round((width + this.margin[0]) / (colWidth + this.margin[0]))
      let h = 0
      if (!autoSizeFlag) {
        h = Math.round((height + this.margin[1]) / (this.rowHeight + this.margin[1]))
      } else {
        h = Math.ceil((height + this.margin[1]) / (this.rowHeight + this.margin[1]))
      }
      // Capping
      w = Math.max(Math.min(w, this.cols - this.innerX), 0)
      h = Math.max(Math.min(h, this.maxRows - this.innerY), 0)
      return {
        w,
        h
      }
    },
    updateWidth (width, colNum) {
      this.containerWidth = width
      if (colNum !== undefined && colNum !== null) {
        this.cols = colNum
      }
    },
    tryMakeDraggable () {
      if (this.interactInstance === null || this.interactInstance === undefined) {
        this.interactInstance = interact(this.$refs.item)
        if (!this.useStyleCursor) {
          this.interactInstance.styleCursor(false)
        }
      }
      if (this.draggable && !this.static) {
        const opts = {
          ignoreFrom: this.dragIgnoreFrom,
          allowFrom: this.dragAllowFrom
        }
        this.interactInstance.draggable(opts)
        if (!this.dragEventSet) {
          this.dragEventSet = true
          this.interactInstance.on('dragstart dragmove dragend', event => {
            this.handleDrag(event)
          })
        }
      } else {
        this.interactInstance.draggable({
          enabled: false
        })
      }
    },
    tryMakeResizable () {
      if (!this.$refs.item) return
      if (this.interactInstance === null || this.interactInstance === undefined) {
        this.interactInstance = interact(this.$refs.item)
        if (!this.useStyleCursor) {
          this.interactInstance.styleCursor(false)
        }
      }
      if (this.resizable && !this.static) {
        const maximum = this.calcPosition(0, 0, this.maxW, this.maxH)
        const minimum = this.calcPosition(0, 0, this.minW, this.minH)
        const resizeOption = {
          edges: {
            left: false,
            right: '.' + this.resizableHandleClass.trim().replace(' ', '.'),
            bottom: '.' + this.resizableHandleClass.trim().replace(' ', '.'),
            top: false
          },
          ignoreFrom: this.resizeIgnoreFrom,
          restrictSize: {
            min: {
              height: minimum.height,
              width: minimum.width
            },
            max: {
              height: maximum.height,
              width: maximum.width
            }
          }
        }
        if (this.preserveAspectRatio) {
          resizeOption.modifiers = [
            interact.modifiers.aspectRatio({
              ratio: 'preserve'
            })
          ]
        }
        this.interactInstance.resizable(resizeOption)
        if (!this.resizeEventSet) {
          this.resizeEventSet = true
          this.interactInstance.on('resizestart resizemove resizeend', (event) => {
            this.handleResize(event)
          })
        }
      } else {
        this.interactInstance.resizable({ enabled: false })
      }
    },
    // Auto set grid item w&h by child node rect size
    autoSize () {
      // ok here we want to calculate if a resize is needed
      this.previousW = this.innerW
      this.previousH = this.innerH

      const newSize = this.$slots.default()[0].elm.getBoundingClientRect()
      const pos = this.calcWH(newSize.height, newSize.width, true)
      if (pos.w < this.minW) {
        pos.w = this.minW
      }
      if (pos.w > this.maxW) {
        pos.w = this.maxW
      }
      if (pos.h < this.minH) {
        pos.h = this.minH
      }
      if (pos.h > this.maxH) {
        pos.h = this.maxH
      }
      if (pos.h < 1) {
        pos.h = 1
      }
      if (pos.w < 1) {
        pos.w = 1
      }
      if (this.innerW !== pos.w || this.innerH !== pos.h) {
        this.$emit('resize', this.id, pos.h, pos.w, newSize.height, newSize.width)
      }
      if (this.previousW !== pos.w || this.previousH !== pos.h) {
        this.$emit('resized', this.id, pos.h, pos.w, newSize.height, newSize.width)
        this.eventBus.emit('resizeEvent', 'resizeend', this.id, this.innerX, this.innerY, pos.h, pos.w)
      }
    }
  }
}
</script>

<style lang="scss">
.vue-grid-item {
  transition: all 200ms ease;
  transition-property: left, top, right;
  border: 0 solid #e0e0e07a;
  /* add right for rtl */

  &.no-touch {
    touch-action: none;
  }

  &.cssTransforms {
    transition-property: transform, border;
    left: 0;
    right: auto;
  }

  &.cssTransforms.render-rtl {
    left: auto;
    right: 0;
  }

  &.resizing {
    opacity: 0.6;
    z-index: 3;
  }

  &.vue-draggable-dragging {
    transition: none;
    z-index: 3;
  }

  &.vue-grid-placeholder {
    background: gray;
    opacity: 0.2;
    transition-duration: 100ms;
    z-index: 2;
    user-select: none;
  }

  & > .vue-resizable-handle {
    position: absolute;
    width: 20px;
    height: 20px;
    bottom: 0;
    right: 0;
    padding: 0 3px 3px 0;
    background: url('') no-repeat bottom right;
    background-origin: content-box;
    box-sizing: border-box;
  }

  & > .vue-rtl-resizable-handle {
    bottom: 0;
    left: 0;
    right: auto;
    padding-left: 3px;
    background: url() no-repeat bottom left;
    background-origin: content-box;
  }

  & > .vue-resizable-handle,
  & > .vue-rtl-resizable-handle {
    cursor: se-resize;
    transition: opacity 300ms;
    opacity: 0;
  }

  &:hover > .vue-resizable-handle,
  &:hover > .vue-rtl-resizable-handle,
  {
    opacity: 1;
  }

  &.disable-userselect {
    user-select: none;
  }

  &.covering {
    box-shadow: 0 0 0 5px #A0A0A0,
    inset 0 10px 27px -8px #141414,
    inset 0px -10px 27px -8px #A31925,
    5px 5px 15px 5px rgba(0, 0, 0, 0);
  }
}
</style>
